/**
 * @file matching_engine.cpp
 * @brief 匹配引擎实现
 *
 * 本文件实现了交易所的核心组件匹配引擎（MatchingEngine）。
 * 实现包括匹配引擎的初始化、启动、停止和清理资源的功能。
 *
 * @author 原作者
 * @date 未知
 */

#include "matching_engine.h"

namespace Exchange {
  /**
   * @brief 匹配引擎构造函数
   * 
   * 初始化匹配引擎，设置无锁队列指针，初始化日志记录器，
   * 并为每个交易品种创建相应的订单簿对象。
   * 
   * @param client_requests 客户端请求无锁队列指针
   * @param client_responses 客户端响应无锁队列指针
   * @param market_updates 市场数据更新无锁队列指针
   */
  MatchingEngine::MatchingEngine(ClientRequestLFQueue *client_requests, ClientResponseLFQueue *client_responses,
                                 MEMarketUpdateLFQueue *market_updates)
      : incoming_requests_(client_requests), outgoing_ogw_responses_(client_responses), outgoing_md_updates_(market_updates),
        logger_("exchange_matching_engine.log") {
    // 为每个交易品种创建订单簿对象
    for(size_t i = 0; i < ticker_order_book_.size(); ++i) {
      ticker_order_book_[i] = new MEOrderBook(i, &logger_, this);
    }
  }

  /**
   * @brief 匹配引擎析构函数
   * 
   * 清理匹配引擎资源，停止匹配引擎线程，
   * 等待线程安全结束，释放队列指针，
   * 并删除所有订单簿对象。
   */
  MatchingEngine::~MatchingEngine() {
    // 停止匹配引擎线程
    stop();

    // 等待1秒，确保线程有足够时间安全结束
    using namespace std::literals::chrono_literals;
    std::this_thread::sleep_for(1s);

    // 释放队列指针
    incoming_requests_ = nullptr;
    outgoing_ogw_responses_ = nullptr;
    outgoing_md_updates_ = nullptr;

    // 删除所有订单簿对象并释放内存
    for(auto& order_book : ticker_order_book_) {
      delete order_book;
      order_book = nullptr;
    }
  }

  /**
   * @brief 启动匹配引擎主线程
   * 
   * 设置运行标志为true，创建并启动匹配引擎的主线程。
   * 线程启动后将执行run方法，开始处理客户端请求。
   * 如果线程创建失败，将触发断言错误。
   */
  auto MatchingEngine::start() -> void {
    // 设置运行标志为true
    run_ = true;
    // 创建并启动匹配引擎线程，如果失败则触发断言错误
    ASSERT(Common::createAndStartThread(-1, "Exchange/MatchingEngine", [this]() { run(); }) != nullptr, "Failed to start MatchingEngine thread.");
  }

  /**
   * @brief 停止匹配引擎主线程
   * 
   * 设置运行标志为false，使匹配引擎的主循环结束，
   * 从而停止匹配引擎线程的运行。
   */
  auto MatchingEngine::stop() -> void {
    // 设置运行标志为false，使主循环结束
    run_ = false;
  }
}
